module mips( clk, rst );
   input   clk;
   input   rst;
   
   wire   PCWr;
   assign PCWr = 1;
   wire [31:0]  PC;
   wire [31:0] NPC;

   wire [31:0] instr;

   wire [5:0] Op;
   wire [5:0] Funct;
   wire [4:0] rs;
   wire [4:0] rt;
   wire [4:0] rd;
   wire [15:0] Imm16;
   wire [25:0] IMM;
   assign Op = instr[31:26];
   assign Funct = instr[5:0];
   assign rs = instr[25:21];
   assign rt = instr[20:16];
   assign rd = instr[15:11];
   assign Imm16 = instr[15:0];
   assign IMM = instr[25:0];

	wire         jump;
	wire [1:0] RegDst;
	wire       Branch;
	wire 		    MemR;
	wire [1:0]  Mem2R;
   wire         DMWr;
   wire         RFWr;
	wire		  Alusrc;
   wire [1:0]  EXTOp;
   wire [4:0]  ALUOp;
   wire [1:0]  NPCOp;
   wire      Alusrc1;

   wire [4:0] gprWeSel;
   wire [31:0]  WD;
   wire [31:0] RD1;
   wire [31:0] RD2;

   wire [31:0] extDataOut;

   PC U_PC (
      .clk(clk), .rst(rst), .PCWr(PCWr), .NPC(NPC), .PC(PC)
   ); 

   im_4k U_IM ( 
      .addr(PC[11:2]) , .dout(instr)
   );

   Ctrl U_Ctrl (
      .jump(jump), .RegDst(RegDst), .Branch(Branch), .MemR(MemR), .Mem2R(Mem2R), .MemW(DMWr), .RegW(RFWr), .Alusrc(Alusrc), .Alusrc1(Alusrc1), .ExtOp(EXTOp), .Aluctrl(ALUOp), .NPCOp(NPCOp), .OpCode(Op), .funct(Funct)
   );

   RF U_RF (
      .A1(rs), .A2(rt), .A3(gprWeSel), .WD(WD), .clk(clk), 
      .RFWr(RFWr), .RD1(RD1), .RD2(RD2)
   );

   EXT U_EXT (
      .Imm16(Imm16), .EXTOp(EXTOp), .Imm32(extDataOut)
   );

   mux4 #( .WIDTH(5)
   )
   U_RegDst(
    .d0(rt), .d1(rd), .d2(5'd31), .d3(5'd0), .s(RegDst), .y(gprWeSel)
   );

   wire [31:0] aluDataOut;
   wire [31:0] aluDataIn1;
   wire [31:0] aluDataIn2;
   assign aluDataIn1 = (Alusrc1==1)?RD2:RD1;
   assign aluDataIn2 = (Alusrc==1)?extDataOut:RD2;
   wire   Zero;
   alu U_Alu(
   .A(aluDataIn1), .B(aluDataIn2), .ALUOp(ALUOp), .C(aluDataOut), .Zero(Zero)
   );

   wire [31:0] PCPLUS4;
   NPC U_NPC (
      .Zero(Zero), .Reg(aluDataOut), .PC(PC), .NPCOp(NPCOp), .IMM(IMM), .NPC(NPC), .PCPLUS4(PCPLUS4)
   );

   wire [31:0] dmDataOut;
   dm_4k U_DMem(
    .addr(aluDataOut[11:2]), .din(RD2), .DMWr(DMWr), .clk(clk), .dout(dmDataOut) 
   );

   mux4 #( .WIDTH(32)
   )
   U_RegSource(
    .d0(aluDataOut), .d1(dmDataOut), .d2(PCPLUS4), .d3(0), .s(Mem2R), .y(WD)
   );

  
endmodule